﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PaperRenderingInterfaces;
using System.ComponentModel.Composition;
using RenderEngineInterfaces;
using HtmlAgilityPack;
using PaperPluginUtilities;
using System.IO;
using DeepZoomPivotConstructor.VisualLib;
using DeepZoomPivotConstructor.PivotLib;

namespace HTMLTablePageScanner
{
    /// <summary>
    /// We have a random web page, and it contains some eps, gif, jpg, etc., links. Turn them into images.
    /// We don't do much parsing of the text, unfortunately.
    /// </summary>
    [Export]
    [PaperRender("HTMLPlotPage")]
    public class PlotPageScanner : IPaperRender
    {
        [Import]
        IWebAccess WebGetter;

        [Import]
        IRenderEngine VisualRenderEngine;

        /// <summary>
        /// Look for links to plot files (only).
        /// </summary>
        /// <param name="renderAddress"></param>
        /// <returns></returns>
        public IEnumerable<PivotImage> Render(string renderAddress)
        {
            ///
            /// Load up the html document
            /// 

            if (renderAddress.IsWebFolder())
            {
                if (!renderAddress.EndsWith("/"))
                {
                    renderAddress += "/";
                }
            }

            Uri mainPage = new Uri(renderAddress);
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(WebGetter.GetUriAsString(mainPage));

            ///
            /// Assume the note title and the web page title are the same
            /// 

            string title = doc.DocumentNode.ExtractHTMLTitle();

            ///
            /// Finding captions is a bit difficult. They can come from three sources:
            /// 1) The text of the link itself
            /// 2) The text right before the link
            /// 3) I give up
            /// 

            string lastDescriptionSeen = "";

            var descripScan = doc.DocumentNode.ScanForText(t => lastDescriptionSeen = t, new string[] { "a" });
            var images = from n in descripScan
                            let urlText = n.Attributes["href"]
                            where urlText != null && urlText.Value != null && urlText.Value.Length > 0
                            let u = new Uri(mainPage, urlText.Value)
                            where u.Scheme.StartsWith("http") && u.IsImageReference()
                            select new
                            {
                                Name = n.InnerText.CleanHTMLText(),
                                Text = lastDescriptionSeen.CleanHTMLText(),
                                Link = u
                            };

            ///
            /// Lots of these guys have the same name - so we had better sort them that way
            /// 

            var groupedImages = from l in images
                                group l by l.Link.ImageFileStem();

            ///
            /// Make a pivot image out of all of those images!
            /// 

            return groupedImages.Select(img =>
                {
                    var bestLink = (from l in img orderby l.Link.ImageTypeRank() select l).First();
                    Visual v = VisualRenderEngine.Render(bestLink.Link, forceAsComposableUnit: true);
                    PivotImage result = null;
                    if (v != null)
                    {
                        result = new PivotImage(v);
                        string bestLinkText = bestLink.Text;

                        if (bestLinkText.EndsWith(":"))
                        {
                            bestLinkText = bestLinkText.Substring(0, bestLinkText.Length - 1);
                        }

                        if (bestLinkText == null || bestLinkText.Length == 0)
                        {
                            bestLinkText = "<no info>";
                        }

                        result.Description = bestLinkText;

                        ///
                        /// For the name use what the link is, or the description (if short enough),
                        /// as long as they look reasonable! :-)
                        /// 

                        result.Name = General.DecideOnImageName(new string[] { bestLink.Name, bestLinkText }, bestLink.Link);

                        ///
                        /// Setup the meta data!
                        /// 

                        img.Execute(l => result.Add("Graphics Files", FileType(l.Link), l.Link));
                        if (title != null)
                        {
                            result.Add("Note Title", title);
                        }
                        result.Add("More Information", "Main Note Page", mainPage);
                        result.Add("Caption", bestLinkText);
                        result.SetDateFromUrl(bestLink.Link, WebGetter);
                    }
                    return result;
                }).Where(i => i != null).AddMissingDate(mainPage, WebGetter);

        }

        /// <summary>
        /// Returns the file extension for the link.
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        private string FileType(Uri uri)
        {
            string last = uri.Segments.Last();
            return Path.GetExtension(last).Substring(1);
        }
    }
}
